/**
 * ============万年历控制器开始===========
 * 万年历控制器 - 处理万年历相关的API请求
 * Calendar Controller - Handle calendar-related API requests
 * 
 * 功能说明：
 * - 提供万年历信息查询功能，包括公历、农历、节气、宜忌等信息
 * - 支持日期格式验证和错误处理
 * - 集成农历服务和运势服务，提供完整的日历信息
 * 
 * 依赖模块说明：
 * - lunarService: 农历服务，提供农历转换和节气计算功能
 * - fortuneService: 运势服务，提供每日运势和宜忌信息
 */

// 导入必要的服务模块 - Import necessary service modules
import lunarService from '../services/lunarService.js';     // 农历服务 - Lunar calendar service
import fortuneService from '../services/fortuneService.js'; // 运势服务 - Fortune service

/**
 * 万年历控制器类 - Calendar Controller Class
 * 负责处理所有与万年历相关的HTTP请求
 */
class CalendarController {
  /**
   * ============获取万年历信息功能开始===========
   * 获取万年历信息
   * Get calendar information
   * 
   * @param {Object} req - Express请求对象，包含查询参数
   * @param {Object} res - Express响应对象，用于返回万年历数据
   * @returns {Promise<void>} 无返回值，通过res对象返回JSON响应
   * @throws {Error} 当日期格式错误或服务调用失败时抛出异常
   * 
   * 功能说明：
   * - 根据提供的日期获取完整的万年历信息
   * - 包括公历日期、农历日期、节气、宜忌、星座等信息
   * - 支持YYYY-MM-DD格式的日期输入验证
   * 
   * 请求参数：
   * - date: 日期字符串，格式为YYYY-MM-DD（如：2024-01-15）
   * 
   * 响应格式：
   * {
   *   success: boolean,     // 操作是否成功
   *   message: string,      // 提示信息
   *   data: {
   *     solar: object,      // 公历信息
   *     lunar: object,      // 农历信息
   *     festivals: array,   // 节日信息
   *     jieQi: string,      // 节气信息
   *     yi: array,          // 宜做的事情
   *     ji: array           // 忌做的事情
   *   }
   * }
   * 
   * 使用示例：
   * GET /api/calendar/info?date=2024-01-15
   * 
   * 异常处理：
   * - 400: 日期参数缺失或格式错误
   * - 500: 服务器内部错误（农历服务调用失败）
   */
  async getCalendarInfo(req, res) {
    try {
      // 第一步：从查询参数中获取日期 - Step 1: Get date from query parameters
      const { date } = req.query;
      
      // 第二步：验证日期参数是否存在 - Step 2: Validate if date parameter exists
      // 这里检查date参数是否存在，因为万年历功能必须基于具体日期
      if (!date) {
        return res.status(400).json({
          success: false,
          message: '请提供日期参数'
        });
      }
      
      // 第三步：验证日期格式 - Step 3: Validate date format
      // 使用正则表达式验证日期格式为YYYY-MM-DD，确保数据格式正确
      // 正则说明：^\d{4}-\d{2}-\d{2}$ 表示4位数字-2位数字-2位数字的格式
      const dateRegex = /^\d{4}-\d{2}-\d{2}$/;
      if (!dateRegex.test(date)) {
        return res.status(400).json({
          success: false,
          message: '日期格式错误，请使用YYYY-MM-DD格式'
        });
      }
      
      // 第四步：调用农历服务获取万年历信息 - Step 4: Call lunar service to get calendar info
      // lunarService.getCalendarInfo() 是核心方法，它会：
      // 1. 将公历日期转换为农历日期
      // 2. 计算节气信息
      // 3. 获取宜忌信息
      // 4. 查找节日信息
      const calendarInfo = lunarService.getCalendarInfo(date);
      
      // 第五步：返回成功响应 - Step 5: Return success response
      res.json({
        success: true,
        data: calendarInfo,
        message: '获取万年历信息成功'
      });
    } catch (error) {
      // 第六步：错误处理 - Step 6: Error handling
      // 记录错误日志，便于调试和监控
      console.error('获取万年历信息失败:', error);
      
      // 返回500错误响应，包含错误信息
      res.status(500).json({
        success: false,
        message: '获取万年历信息失败',
        error: error.message
      });
    }
  }
  
  /**
   * ============获取月份万年历功能开始===========
   * 获取月份万年历
   * Get monthly calendar
   * 
   * @param {Object} req - Express请求对象，包含年份和月份查询参数
   * @param {Object} res - Express响应对象，用于返回月份万年历数据
   * @returns {Promise<void>} 无返回值，通过res对象返回JSON响应
   * @throws {Error} 当年份月份参数错误或服务调用失败时抛出异常
   * 
   * 功能说明：
   * - 获取指定年月的完整万年历信息
   * - 返回该月每一天的公历、农历、节气、宜忌等信息
   * - 支持1900-2100年范围内的年份查询
   * 
   * 请求参数：
   * - year: 年份，数字格式（如：2024）
   * - month: 月份，数字格式1-12（如：1表示1月）
   * 
   * 响应格式：
   * {
   *   success: boolean,     // 操作是否成功
   *   message: string,      // 提示信息
   *   data: [
   *     {
   *       date: string,     // 日期YYYY-MM-DD
   *       solar: object,    // 公历信息
   *       lunar: object,    // 农历信息
   *       festivals: array, // 节日信息
   *       jieQi: string,    // 节气信息
   *       yi: array,        // 宜做的事情
   *       ji: array         // 忌做的事情
   *     }
   *   ]
   * }
   * 
   * 使用示例：
   * GET /api/calendar/monthly?year=2024&month=1
   * 
   * 异常处理：
   * - 400: 年份或月份参数缺失、格式错误或超出范围
   * - 500: 服务器内部错误（农历服务调用失败）
   */
  async getMonthlyCalendar(req, res) {
    try {
      // 第一步：从查询参数中获取年份和月份 - Step 1: Get year and month from query parameters
      const { year, month } = req.query;
      
      // 第二步：验证年份和月份参数是否存在 - Step 2: Validate if year and month parameters exist
      // 月份万年历需要明确的年份和月份才能计算
      if (!year || !month) {
        return res.status(400).json({
          success: false,
          message: '请提供年份和月份参数'
        });
      }
      
      // 第三步：将字符串参数转换为数字 - Step 3: Convert string parameters to numbers
      // parseInt() 用于将字符串转换为整数，便于后续数值比较和计算
      const yearNum = parseInt(year);
      const monthNum = parseInt(month);
      
      // 第四步：验证年份和月份的有效范围 - Step 4: Validate year and month ranges
      // 年份限制在1900-2100年，这是农历算法的有效范围
      // 月份限制在1-12，这是标准的月份范围
      if (yearNum < 1900 || yearNum > 2100 || monthNum < 1 || monthNum > 12) {
        return res.status(400).json({
          success: false,
          message: '年份或月份参数无效'
        });
      }
      
      // 第五步：初始化月份万年历数组 - Step 5: Initialize monthly calendar array
      const monthlyCalendar = [];
      
      // 第六步：计算该月的天数 - Step 6: Calculate days in the month
      // new Date(year, month, 0) 会返回上个月的最后一天
      // 所以 new Date(yearNum, monthNum, 0) 返回当前月的最后一天
      // getDate() 获取这一天是几号，即该月的总天数
      const daysInMonth = new Date(yearNum, monthNum, 0).getDate();
      
      // 第七步：循环处理该月的每一天 - Step 7: Loop through each day of the month
      for (let day = 1; day <= daysInMonth; day++) {
        // 第八步：构建标准日期格式 - Step 8: Build standard date format
        // padStart(2, '0') 确保月份和日期都是两位数格式（如：01, 02）
        const date = `${yearNum}-${monthNum.toString().padStart(2, '0')}-${day.toString().padStart(2, '0')}`;
        
        // 第九步：获取每一天的万年历信息 - Step 9: Get calendar info for each day
        const calendarInfo = lunarService.getCalendarInfo(date);
        
        // 第十步：构建每日万年历数据对象 - Step 10: Build daily calendar data object
        monthlyCalendar.push({
          date,                                                    // 完整日期字符串
          day,                                                     // 日期数字
          weekDay: new Date(date).getDay(),                       // 星期几（0-6，0表示周日）
          solar: calendarInfo.solar,                              // 公历信息
          lunar: {                                                // 农历信息
            year: calendarInfo.lunar.year,                        // 农历年份
            month: calendarInfo.lunar.month,                      // 农历月份
            day: calendarInfo.lunar.day,                          // 农历日期
            monthCn: calendarInfo.lunar.monthCn,                  // 农历月份中文
            dayCn: calendarInfo.lunar.dayCn,                      // 农历日期中文
            isLeapMonth: calendarInfo.lunar.isLeapMonth           // 是否闰月
          },
          festival: calendarInfo.festival,                        // 节日信息
          jieQi: calendarInfo.lunar.jieQi,                       // 节气信息
          isToday: date === new Date().toISOString().split('T')[0] // 是否为今天
        });
      }
      
      // 第十一步：返回月份万年历成功响应 - Step 11: Return monthly calendar success response
      res.json({
        success: true,
        data: {
          year: yearNum,                                          // 年份
          month: monthNum,                                        // 月份
          days: monthlyCalendar                                   // 该月所有日期的万年历信息
        },
        message: '获取月份万年历成功'
      });
    } catch (error) {
      // 第十二步：错误处理 - Step 12: Error handling
      // 记录错误日志，便于调试和监控
      console.error('获取月份万年历失败:', error);
      
      // 返回500错误响应，包含错误信息
      res.status(500).json({
        success: false,
        message: '获取月份万年历失败',
        error: error.message
      });
    }
  }
  
  /**
   * ============获取黄道吉日功能开始===========
   * 获取黄道吉日
   * Get auspicious days
   * 
   * @param {Object} req - Express请求对象，包含年份和月份查询参数
   * @param {Object} res - Express响应对象，用于返回黄道吉日数据
   * @returns {Promise<void>} 无返回值，通过res对象返回JSON响应
   * @throws {Error} 当年份月份参数错误或服务调用失败时抛出异常
   * 
   * 功能说明：
   * - 根据传统农历算法计算指定月份的黄道吉日
   * - 黄道吉日是指适合办重要事情的好日子
   * - 基于天干地支、五行相生相克等传统理论计算
   * 
   * 请求参数：
   * - year: 年份，数字格式（如：2024）
   * - month: 月份，数字格式1-12（如：1表示1月）
   * 
   * 响应格式：
   * {
   *   success: boolean,     // 操作是否成功
   *   message: string,      // 提示信息
   *   data: [
   *     {
   *       date: string,     // 吉日日期YYYY-MM-DD
   *       lunar: object,    // 农历信息
   *       yi: array,        // 宜做的事情
   *       ji: array,        // 忌做的事情
   *       level: string     // 吉日等级（大吉、中吉、小吉）
   *     }
   *   ]
   * }
   * 
   * 使用示例：
   * GET /api/calendar/auspicious?year=2024&month=1
   * 
   * 异常处理：
   * - 400: 年份或月份参数缺失
   * - 500: 服务器内部错误（农历服务调用失败）
   */
  async getAuspiciousDays(req, res) {
    try {
      // 第一步：从查询参数中获取年份和月份 - Step 1: Get year and month from query parameters
      const { year, month } = req.query;
      
      // 第二步：验证年份和月份参数是否存在 - Step 2: Validate if year and month parameters exist
      // 黄道吉日计算需要明确的年份和月份
      if (!year || !month) {
        return res.status(400).json({
          success: false,
          message: '请提供年份和月份参数'
        });
      }
      
      // 第三步：调用农历服务获取黄道吉日 - Step 3: Call lunar service to get auspicious days
      // parseInt() 将字符串转换为整数，lunarService.getAuspiciousDays() 需要数字参数
      const auspiciousDays = lunarService.getAuspiciousDays(parseInt(year), parseInt(month));
      
      // 第四步：返回成功响应 - Step 4: Return success response
      res.json({
        success: true,
        data: auspiciousDays,
        message: '获取黄道吉日成功'
      });
    } catch (error) {
      // 第五步：错误处理 - Step 5: Error handling
      // 记录错误日志，便于调试和监控
      console.error('获取黄道吉日失败:', error);
      
      // 返回500错误响应，包含错误信息
      res.status(500).json({
        success: false,
        message: '获取黄道吉日失败',
        error: error.message
      });
    }
  }
  
  /**
   * ============获取时辰宜忌功能开始===========
   * 获取时辰宜忌
   * Get time Yi Ji (suitable and unsuitable activities)
   * 
   * @param {Object} req - Express请求对象，包含日期查询参数
   * @param {Object} res - Express响应对象，用于返回时辰宜忌数据
   * @returns {Promise<void>} 无返回值，通过res对象返回JSON响应
   * @throws {Error} 当日期参数错误或服务调用失败时抛出异常
   * 
   * 功能说明：
   * - 获取指定日期每个时辰（2小时为一个时辰）的宜忌信息
   * - 基于传统的时辰吉凶理论，为用户提供详细的时间选择建议
   * - 一天共12个时辰：子、丑、寅、卯、辰、巳、午、未、申、酉、戌、亥
   * 
   * 请求参数：
   * - date: 日期字符串，格式为YYYY-MM-DD（如：2024-01-15）
   * 
   * 响应格式：
   * {
   *   success: boolean,     // 操作是否成功
   *   message: string,      // 提示信息
   *   data: [
   *     {
   *       time: string,     // 时辰名称（如：子时）
   *       period: string,   // 时间段（如：23:00-01:00）
   *       yi: array,        // 该时辰宜做的事情
   *       ji: array,        // 该时辰忌做的事情
   *       level: string     // 吉凶等级（吉、凶、平）
   *     }
   *   ]
   * }
   * 
   * 使用示例：
   * GET /api/calendar/time-yiji?date=2024-01-15
   * 
   * 异常处理：
   * - 400: 日期参数缺失或格式错误
   * - 500: 服务器内部错误（农历服务调用失败）
   */
  async getTimeYiJi(req, res) {
    try {
      // 第一步：从查询参数中获取日期 - Step 1: Get date from query parameters
      const { date } = req.query;
      
      // 第二步：验证日期参数是否存在 - Step 2: Validate if date parameter exists
      // 时辰宜忌计算需要具体的日期
      if (!date) {
        return res.status(400).json({
          success: false,
          message: '请提供日期参数'
        });
      }
      
      // 第三步：调用农历服务获取时辰宜忌 - Step 3: Call lunar service to get time Yi Ji
      // lunarService.getTimeYiJi() 会计算该日期12个时辰的宜忌信息
      const timeYiJi = lunarService.getTimeYiJi(date);
      
      // 第四步：返回成功响应 - Step 4: Return success response
      res.json({
        success: true,
        data: timeYiJi,
        message: '获取时辰宜忌成功'
      });
    } catch (error) {
      // 第五步：错误处理 - Step 5: Error handling
      // 记录错误日志，便于调试和监控
      console.error('获取时辰宜忌失败:', error);
      
      // 返回500错误响应，包含错误信息
      res.status(500).json({
        success: false,
        message: '获取时辰宜忌失败',
        error: error.message
      });
    }
  }
  
  /**
   * ============获取节气信息功能开始===========
   * 获取节气信息
   * Get solar terms information
   * 
   * @param {Object} req - Express请求对象，包含年份查询参数
   * @param {Object} res - Express响应对象，用于返回节气数据
   * @returns {Promise<void>} 无返回值，通过res对象返回JSON响应
   * @throws {Error} 当年份参数错误或服务调用失败时抛出异常
   * 
   * 功能说明：
   * - 获取指定年份的24节气信息
   * - 节气是中国传统历法中表示季节变迁的24个特定时间点
   * - 包括立春、雨水、惊蛰、春分等，每个节气都有具体的日期和时间
   * 
   * 请求参数：
   * - year: 年份，数字格式（如：2024）
   * 
   * 响应格式：
   * {
   *   success: boolean,     // 操作是否成功
   *   message: string,      // 提示信息
   *   data: [
   *     {
   *       name: string,     // 节气名称（如：立春）
   *       date: string,     // 节气日期YYYY-MM-DD
   *       time: string,     // 节气具体时间HH:MM:SS
   *       description: string // 节气描述和特点
   *     }
   *   ]
   * }
   * 
   * 使用示例：
   * GET /api/calendar/solar-terms?year=2024
   * 
   * 异常处理：
   * - 400: 年份参数缺失
   * - 500: 服务器内部错误（农历服务调用失败）
   */
  async getSolarTerms(req, res) {
    try {
      // 第一步：从查询参数中获取年份 - Step 1: Get year from query parameters
      const { year } = req.query;
      
      // 第二步：验证年份参数是否存在 - Step 2: Validate if year parameter exists
      // 节气信息需要明确的年份才能计算
      if (!year) {
        return res.status(400).json({
          success: false,
          message: '请提供年份参数'
        });
      }
      
      const solarTerms = lunarService.getSolarTerms(parseInt(year));
      
      res.json({
        success: true,
        data: solarTerms,
        message: '获取节气信息成功'
      });
    } catch (error) {
      console.error('获取节气信息失败:', error);
      res.status(500).json({
        success: false,
        message: '获取节气信息失败',
        error: error.message
      });
    }
  }
}

export default new CalendarController();